/**
 * 树形View控件，包含基本的树处理操作，View路径：module/component/views/TreeView
 * <pre>
 * 初始化树的参数为：{config:{tree:{Config options参数},callback:{Event相关事件}}}。
 * 例如：new TreeView({config:{tree:{idKey:,data...},callback:{onExpand:function(e){}}}});
 * </pre>
 * @class ngc.component.view.TreeView
 */
define([ "module/component/views/CommonUIView" ], function(CommonView) {
	var treeView = CommonView.extend({	
		
		afterRender : function() {
			this._initTree();			
			
		},
		
		getTree : function() {
			return this.getComponentObject();
		},
        /**
         * @method cancelSelectedNode
         * 取消节点的选中状态。
         * @param  {Object} [node] 需要取消选中状态的节点。
         */
        cancelSelectedNode: function (node) {
        	this.getTree().tree('cancelSelectedNode', node);
        },

		/**
		 * @method 重新加载树的节点数据
		 * @param newNodes :
		 *            Array 需要增加的节点数据 JSON 对象集合
		 * 
		 */
		reloadData : function(newNodes) {
			this.getTree().tree('reloadData', newNodes);
		},
        /**
         * @method expandNode
         * 展开 / 折叠 指定的节点,可以触发 beforeExpand / onExpand 或 beforeCollapse / onCollapse 事件回调函数。
         * @param  {Object} node 需要 展开 / 折叠 的节点数据
         * @param  {Boolean} [expandFlag] expandFlag = true 表示展开节点 expandFlag = false 表示折叠节点；省略此参数，则根据对此节点的展开状态进行 toggle 切换
         * @param  {Boolean} [sonSign = false] sonSign = true表示全部子孙节点进行与expandFlag相同的操作,sonSign = false 表示只影响此节点，对于其子孙节点无任何影响;
         * @param  {Boolean} [focus = true] focus = true 表示 展开 / 折叠 操作后，通过设置焦点保证此焦点进入可视区域内,focus = false 表示 展开 / 折叠 操作后，不设置任何焦点
         * @param  {Boolean} [callbackFlag = false] callbackFlag = true 表示执行此方法时触发 beforeExpand / onExpand 或 beforeCollapse / onCollapse 事件回调函数 ;callbackFlag = false 表示执行此方法时不触发事件回调函数
         * @return {Boolean} 返回值表示最终实际操作情况:true 表示 展开 节点;false 表示 折叠 节点;null 表示 不是父节点
         */
        expandNode: function (node, expandFlag, sonSign, focus, callbackFlag) {
        	return this.getTree().tree('expandNode', node, expandFlag, sonSign, focus, callbackFlag);
        },
        
        /**
         * @method expandAll
         * 展开 / 折叠 全部节点
         * 此方法不会触发 beforeExpand / onExpand 和 beforeCollapse / onCollapse 事件回调函数。
         * @param  {Boolean} expandFlag expandFlag = true 表示 展开 全部节点;expandFlag = false 表示 折叠 全部节点
         * @return {Boolean}  true 表示 展开 全部节点;false 表示 折叠 全部节点;null 表示 不存在任何父节点
         */
        expandAll: function (expandFlag) {
        	return this.getTree().tree('expandAll', expandFlag);
        },
        
    	/**
         * @method getCheckedNodes
         * 获取输入框被勾选 或 未勾选的节点集合。[check.enable = true 时有效]
         * @param  {Boolean} [checked=true]  true 表示获取 被勾选 的节点集合;false 表示获取 未勾选 的节点集合
         * @return {Array}         返回全部符合要求的节点集合 Array
         */
        getCheckedNodes:function(checked){
        	return this.getTree().tree('getCheckedNodes', checked);
        },
        
        /**
         * 滚动某个节点到可视区域
         * @param node 需要到可视区域的高度
         */
        scrollToView:function(node){
        	if(node&&node.tId){
        		var container = this.getComponentObject().children("ul"), scrollTo = $("#"+node.tId);
            	var _h = scrollTo.offset().top - container.offset().top + container.scrollTop();
            	container.animate({scrollTop:_h});
        	}       	
        },
		
		/**
		 * @method 获取树的当前被选中的节点数据集合
		 * @return {Array} 当前被选中的节点数据集合
		 */
		getSelectedNodes: function(){
			return this.getTree().tree('getSelectedNodes');
		},
		
		/**
		 * 获取某个节点的根节点
		 * @param {Object} node 树的某个节点
		 */
		getRootNode:function(node){
			var _pre = node.getParentNode();
			if(!_pre){
				return node;
			}else{
				return this.getRootNode(_pre);
			}
		},
		
        /**
         * @method  destroy
         * 销毁tree对象
         */
        _destroy: function () {
        	return this.getTree().tree('_destroy');
        },
        
        /**
         * @method selectNode
         * 选中指定节点
         * @param  {Object} node 需要被选中的节点数据(请务必保证此节点数据对象 是fish.tree内部的数据对象)
         * @param  {Boolean} [addFlag]    addFlag = true 表示追加选中，会出现多点同时被选中的情况
         *                                addFlag = false 表示单独选中，原先被选中的节点会被取消选中状态
         *                                setting.view.selectedMulti = false 时，此参数无效，始终进行单独选中
         */
		selectNode:function(node,addFlag){
			this.getTree().tree('selectNode',node,addFlag);
		},
		/**
         * @method getNodeByParam
         * 根据节点数据的属性搜索，获取条件完全匹配的节点数据 JSON 对象
         * @param  {String} key 需要精确匹配的属性名称
         * @param  value 需要精确匹配的属性值，可以是任何类型，只要保证与 key 指定的属性值保持一致即可
         * @param  {Object} [parentNode] 搜索范围，指定在某个父节点下的子节点中进行搜索,忽略此参数，表示在全部节点中搜索
         * @return {Object} 匹配精确搜索的节点数据
         *                    1、如无结果，返回 null
         *                    2、如有多个节点满足查询条件，只返回第一个匹配到的节点
         */
		getNodeByParam:function(key, value, parentNode){
			return this.getTree().tree('getNodeByParam',key, value, parentNode);
		},
		/**
		   * 删除节点,删除节点可以触发 beforeRemove / onRemove 事件
		   * @param node
		   * @private
		   */
		removeNode:function( node, callbackFlag ){
			this.getTree().tree('removeNode',node,callbackFlag);
		},
		
        /**
         * 移动节点
         * @method moveNode
         * @param  {Object}  targetNode 移动到的目标节点
         * @param  {Object}  node       需要被移动的节点
         * @param  {String}  moveType   移动类型
         *  "inner" : 作为目标节点的子节点
         *  "prev": 作为目标节点的前一个节点
         *  "next" : 作为目标节点的后一个节点
         * @param  {Boolean} isSilent  移动完成之后是否自动展开父节点.isSilent = true 不展开父节点.isSilent = false 或者忽略此配置，展开父节点.
         * @return {Object}             返回被移动的节点.
         */
		moveNode:function(targetNode, node, moveType, isSilent){
			return this.getTree().tree('moveNode',targetNode, node, moveType, isSilent);
		},
		 /**
         * @method refresh
         * 刷新tree,会清空dom结构，根据数据和配置项重新构建；没有特殊必要，尽量不要使用此方法。单个节点更新请使用 updateNode 方法
         */
        refresh: function () {
        	this.getTree().tree('refresh');
        },
        /**
         * @method isSelectedNode
         * 判断传入的节点当前是否被选中
         * @param  {Object}  node 节点数据
         * @return {Boolean}      如果传入的节点当前是被选中的，返回true；否则返回false
         */
		isSelectedNode:function( node ){
			return this.getTree().tree('isSelectedNode',node);
		},
		
		/**
		 * 设置树的高度
		 * @param {Number} height 树的高度，单位为像素
		 */
		setHeight:function(height){
			this.getTree().children("ul").height(height);
		},
        /**
         * @method removeChildNodes
         * 清空某父节点的子节点。
         * 1、清空子节点后，父节点会自动变为叶子节点，如需要父节点保持父节点状态，请设置 setting.data.keep.parent 属性。
         * 2、请勿用此方法清空根节点，如果需要清空根节点,使用$treeDom.tree('option','fNodes',nodesData)
         * 3、此方法不会触发任何事件回调函数。
         * @param  {Object} node 需要清空子节点的父节点数据
         * @return {Array}      将该父节点的子节点数据返回，如果不存在则返回 null
         */
        removeChildNodes: function (node) {
        	return this.getTree().tree('removeChildNodes',node);
        },
        
        /**
         * @method transformToTreeNodes
         * 将简单 Array 格式数据转换为 Tree 使用的标准 JSON 嵌套数据格式。
         * 使用此方法，请务必设置节点唯一标识属性名称 data.simpleData.idKey 和 父节点唯一标识属性名称 data.simpleData.pIdKey，并且让数据满足父子关系。
         * @param  {Array} simpleNodes 需要被转换的简单 Array 格式数据 或 某个单独的数据对象
         * @return         tree使用的标准数据，子节点都存在于父节点数据的 children 属性中
         */
        transformToTreeNodes: function (simpleNodes) {
        	return this.getTree().tree('transformTozTreeNodes',simpleNodes);
        },
        
        /**
         * @method transformToArray
         * 将 tree使用的标准 JSON 嵌套格式的数据转换为简单 Array 格式。(免去用户自行编写递归遍历全部节点的麻烦)
         * @param  {Array} nodes 需要被转换的 tree 节点数据对象集合 或 某个单独节点的数据对象
         * @return 将 tree 使用的标准 JSON 嵌套格式的数据转换为简单 Array 格式
         */
        transformToArray: function (nodes) {
        	return this.getTree().tree('transformToArray',nodes);
        },
        /**
         * @method updateNode
         * 更新某节点数据，主要用于该节点显示属性的更新。
         * 1、可针对 name、target、 url、icon、 iconSkin、checked、nocheck 等这几个用于显示效果的参数进行更新，其他用于 TreeNodes 的参数请不要随意更新，对于展开节点，还请调用 expandNode方法，因此请勿随意修改 open 属性。
         * 2、用此方法修改 checked 勾选状态不会触发 beforeCheck / onCheck 事件回调函数。
         * @param  {Object} node          指定需要更新的节点 JSON 数据,请务必保证此节点数据对象 是 Tree 内部的数据对象
         * @param  checkTypeFlag [description]
         */
        updateNode: function (node, checkTypeFlag) {
        	this.getTree().tree('updateNode',node, checkTypeFlag);
        },
        /**
         * @method getNodeIndex
         * 获取某节点在同级节点中的序号（从0开始）
         * @param  {Object} node 需要查询顺序的节点 JSON 数据对象
         * @return {Number}      返回值从 0 开始计数,如果不存在该节点数据，返回 -1
         */
        getNodeIndex: function (node) {
        	return this.getTree().tree('getNodeIndex',node);
        },
        
        /**
         * @method getNodesByParamFuzzy
         * 根据节点数据的属性搜索，获取条件模糊匹配的节点数据 JSON 对象集合
         * @param  {String} key        需要模糊匹配的属性名称
         * @param  value      需要模糊匹配的属性值,模糊匹配只能针对 String 类型的数据
         * @param  {Object} [parentNode] 可以指定在某个父节点下的子节点中搜索,忽略此参数，表示在全部节点中搜索
         * @return {Array}       匹配精确搜索的节点数据集合,如无结果，返回 [ ]
         */
        getNodesByParamFuzzy: function (key, value, parentNode) {
        	return this.getTree().tree('getNodesByParamFuzzy',key, value, parentNode);
        },
        
        /**
         * @method getNodes
         * 获取 zTree 的全部节点数据
         * @return {Array} 全部节点数据
         */
        getNodes: function () {
        	return this.getTree().tree('getNodes');
        },
        
        /**
         * @method getNodesByParam
         * 根据节点数据的属性搜索，获取条件完全匹配的节点数据 JSON 对象集合
         * @param  {String} key        需要精确匹配的属性名称
         * @param  value      需要精确匹配的属性值，可以是任何类型，只要保证与 key 指定的属性值保持一致即可
         * @param  {Object} [parentNode] 可以指定在某个父节点下的子节点中搜索,忽略此参数，表示在全部节点中搜索
         * @return {Array}       匹配精确搜索的节点数据集合,如无结果，返回 [ ]
         */
        getNodesByParam: function (key, value, parentNode) {
        	return this.getTree().tree('getNodesByParam',key, value, parentNode);
        },
        /**
         * @method getNodeByTId
         * 根据 zTree 的唯一标识 tId 快速获取节点 JSON 数据对象,通过内部的 cache 获取，不需要遍历节点
         * @param  {String} tId 节点在 zTree 内的唯一标识 tId
         * @return {Object}     tId 对应的节点 JSON 数据对象
         */
        getNodeByTId: function (tId) {
        	return this.getTree().tree('getNodeByTId',tId);
        },
        
        /**
         * @method  getNodesByFilter
         * 根据自定义规则搜索节点数据 JSON 对象集合 或 单个节点数据
         * @param  {Function}  filter     自定义过滤器函数 function filter(node) {...},filter 参数：node (节点数据 JSON)filter 返回值：boolean (true 表示符合搜索条件；false 表示不符合搜索条件)
         * @param  {Boolean} [isSingle=false]    true 表示只查找单个节点,false表示查找节点集合
         * @param  {Object}  [parentNode]  可以指定在某个父节点下的子节点中搜索,忽略此参数，表示在全部节点中搜索
         * @param  {Object} [invokeParam] 用户自定义的数据对象，用于 filter 中进行计算
         * @return isSingle = true 返回 第一个找到的节点数据 JSON，无结果时返回 null;isSingle = false 返回 节点数据集合 Array(JSON)，无结果时返回 [ ]
         */
        getNodesByFilter: function (filter, isSingle, parentNode, invokeParam) {
        	return this.getTree().tree('getNodesByFilter',filter, isSingle, parentNode, invokeParam);
        },

		/**
		 * @method 添加节点数据
		 * @param parentNode :
		 *            Object 指定的父节点，如果增加根节点，请设置 parentNode 为 null
		 *            即可。请务必保证此节点数据对象 是 Tree 内部的数据对象
		 * @param newNodes :
		 *            Array 需要增加的节点数据 JSON 对象集合，数据只需要满足 Tree
		 *            的节点数据必需的属性即可;增加一个节点的时候，可以不使用数组
		 * @param isSilent :
		 *            Boolean 设定增加节点后是否自动展开父节点。isSilent = true
		 *            时，不展开父节点,其他值或缺省状态都自动展开
		 */
		addNodes : function(parentNode, newNodes, isSilent) {
			this.getTree().tree('addNodes', parentNode, newNodes, isSilent);
		},

		/**
		 * @method 树的初始化
		 */
		_initTree : function() {
			if (!this.getOptionConfig()) {
				this.setOptionConfig({
					tree:{
						data : {
							simpleData : {
								enable : true
							}
						}
					},
					callback : {
						beforeExpand : function(event) {

						}
					}

				});
			}
			
			this.getComponentObject().tree(this.getOptionConfig().tree);
			if(this.getOptionConfig().tree.view&&this.getOptionConfig().tree.view.height)
				this.setHeight(this.getOptionConfig().tree.view.height);
			
			//Tree增加回调函数
			this._addCallBack();
			this.getTree().on('tree:onrightclick',function(e,node){
				this.selectNode(node);
			}.bind(this));
			
			this.trigger("viewRenderAfter");
			
			this.setInitFlag(true);
		},
		
		_addCallBack:function(){
			var _callBacks = {"beforeAsync":{},"beforeClick":{},"beforeDblClick":{},"beforeRightClick":{},"beforeMouseDown":{},"beforeMouseUp":{},"beforeExpand":{},"beforeCollapse":{},"beforeRemove":{},"onAsyncError":{},"onAsyncSuccess":{},"onNodeCreated":{},"onClick":{},"onDblClick":{},"onRightClick":{},"onMouseDown":{},"onMouseUp":{},"onExpand":{},"onCollapse":{},"onRemove":{},"beforeCheck":{},"onCheck":{},"beforeDrag":{},"beforeDragOpen":{},"beforeDrop":{},"beforeEditName":{},"beforeRename":{},"onDrag":{},"onDragMove":{},"onDrop":{},"onRename":{}};
			if(this.getOptionConfig().callback){
				var that = this;
				$.each(this.getOptionConfig().callback,function(k){
					var _fn = k;
					
					if(_callBacks[k]){
						that.getTree().tree("instance").options.callback[_fn] = that.getOptionConfig().callback[_fn];
						that.getTree().on("tree:"+k,function(){
							if(ngc.isFunction(that.getOptionConfig().callback[_fn]))
								return that.getOptionConfig().callback[_fn].apply(that,arguments);
						});
					}
					that.getTree().on("tree:"+k.toLowerCase(),function(){
						if(ngc.isFunction(that.getOptionConfig().callback[_fn]))
							return that.getOptionConfig().callback[_fn].apply(that,arguments);
					});
					
					
				});
				
			}
			
		},
		_doOnBeforeMenu:function(e){
			if(this.getSelectedNodes().length==0)return false;
			return true;
		},
		/**
		 * @method 获取右键可用区域
		 */
		_getMenuClickObj:function(){
			return this.getComponentObject();
		},
		/**
		 * @method 右键菜单支持，增加事件处理
		 */
		onMenuEvent:function(id,menu,param){
			this.trigger('onClickMenu',id,this.getSelectedNodes(),param,menu);
			
		}
		

	});

	return treeView;

})

	/**
    * @cfg {Object} check 节点选中操作相关的配置项
    * @cfg {Boolean} check.enable 设置 Tree 的节点上是否显示 checkbox / radio;默认值false
    * @cfg {Boolean} check.autoCheckTrigger 设置自动关联勾选时是否触发 beforeCheck / onCheck 事件回调函数。[check.enable = true 且 check.chkStyle = "checkbox" 时生效]
    *      1、如果设置 setting.check.chkboxType = { "Y": "", "N": "" }，将不会有任何自动关联勾选的操作。
    *      2、如果开启触发，对于节点较多的树将会影响性能，因为所有被联动勾选的操作都会触发事件回调函数，请根据需要决定是否使用此功能。
    * @cfg {String} check.chkStyle 勾选框类型(checkbox 或 radio）[check.enable = true 时生效],默认值："checkbox"
    * @cfg {Object} check.chkboxType 勾选 checkbox 对于父子节点的关联关系。[check.enable = true 且 check.chkStyle = "checkbox" 时生效] 默认值：{ "Y": "ps", "N": "ps" }
    *      Y 属性定义 checkbox 被勾选后的情况；
    *      N 属性定义 checkbox 取消勾选后的情况；
    *      "p" 表示操作会影响父级节点；
    *      "s" 表示操作会影响子级节点。
    *      请注意大小写，不要改变
    * @cfg {Boolean} check.nocheckInherit 当父节点设置 nocheck = true 时，设置子节点是否自动继承 nocheck = true [check.enable = true 时生效]
    * @cfg {Boolean} check.chkDisabledInherit  当父节点设置 chkDisabled = true 时，设置子节点是否自动继承 chkDisabled = true 。
    */


          /**
             * @cfg {Object} view 页面展示相关的配置
             * @cfg {Number} view.height 树的高度，单位为像素
             * @cfg {Function} view.addDiyDom=null 用于在节点上固定显示用户自定义控件;函数有一个入参，节点的数据
             * @cfg {Boolean} [view.autoCancelSelected=true] 点击节点时，按下 Ctrl 或 Cmd 键是否允许取消选择操作。true / false 分别表示 支持 / 不支持 配合 Ctrl 或 Cmd 键进行取消节点选择的操作
             * @cfg {Boolean} [view.dblClickExpand=true] 双击节点时，是否自动展开父节点的标识
             * @cfg {Object} view.fontCss 个性化文字样式，只针对 zTree 在节点上显示的A对象，例如：{color:"#ff0011", background:"blue"}
             * @cfg {Boolean} [view.nameIsHTML=false] 设置 name 属性是否支持 HTML 脚本
             * @cfg {Boolean} [view.selectedMulti=true] 设置是否允许同时选中多个节点。
             * @cfg {Boolean} [view.showIcon=true] 设置 是否显示节点的图标。也可以传入一个函数，返回true或者false。函数有两个入参，第一个是tree的id，第二个是节点的数据
             * @cfg {Boolean} [view.showLine=true]  设置 是否显示节点之间的连线。
             * @cfg {Boolean} [view.showTitle=true] 设置 是否显示节点的 title 提示信息(即节点 DOM 的 title 属性)。
             * true / false 分别表示 显示 / 隐藏 提示信息
             * 如果 options.view.showTitle = true & options.data.key.title = '',tree 会自动使用 options.data.key.name 指定的节点名称当做 title
             * showTitle 也可以传入一个函数，通过函数的返回值确定某个节点是否应该显示title，函数有两个入参，第一个是tree的id，第二个是节点的数据
             * @cfg {Boolean} [view.txtSelectedEnable=false] 设置 是否允许可以选择 tree DOM 内的文本,默认不可选择
             *
             * @cfg {Function} [view.addHoverDom=null] 鼠标移入或选中节点处理
             * <pre>
             *     function addHoverDom(treeNode) {
             *         var treeNodeId = treeNode.tId;
             *         // do something here
             *     }
             * </pre>
             * @cfg {Function} [view.removeHoverDom=null] 鼠标移出或去选中节点处理
             * <pre>
             *     function removeHoverDom(treeNode) {
             *         var treeNodeId = treeNode.tId;
             *         // do something here
             *     }
             * </pre>
             */
           /**
             * @cfg {Object} callback 回调函数的配置
             * @cfg {Function} callback.beforeClick=null 用于捕获单击节点之前的事件回调函数，并且根据返回值确定是否允许单击操作。函数的参数说明：
             *        treeNode 被单击的节点 JSON 数据对象
             *        clickFlag    节点被点击后的选中操作类型，详细看下表
             *
             *        clickFlag    selectedMulti    autoCancelSelected && event.ctrlKey / metaKey    isSelected    选中操作
             *        1                true                    false                                    false    普通选中
             *        1                true                    false                                    true    普通选中
             *        2                true                    true                                    false    追加选中
             *        0                true                    true                                    true    取消选中
             *        1                false                    false                                    false    普通选中
             *        1                false                    false                                    true    普通选中
             *        1                false                    true                                    false    普通选中
             *        0                false                    true                                    true    取消选中
             *
             *        返回值是 true / false
             *        如果返回 false，tree将不会选中节点，也无法触发 onClick 事件回调函数
             *
             * @cfg {Function} callback.beforeDblClick=null 用于捕获 tree 上鼠标双击之前的事件回调函数，并且根据返回值确定触发 onDblClick 事件回调函数. Function 参数说明
             *        treeNode 被单击的节点 JSON 数据对象             *
             *        返回值是 true / false
             *        如果返回 false，将仅仅无法触发 onDblClick 事件回调函数，对其他操作无任何影响
             *        此事件回调函数对双击节点展开功能无任何影响，如果需要设置请参考 view.dblClickExpand 属性
             *
             * @cfg {Function} callback.beforeRightClick=null 用于捕获 tree 上鼠标右键点击之前的事件回调函数，并且根据返回值确定触发 onRightClick 事件回调函数.参数是event和treeNode
             * @cfg {Function} callback.beforeMouseDown=null
             * @cfg {Function} callback.beforeMouseUp=null beforeMouseUp和beforeMouseDown分别用于捕获 tree 上鼠标按键松开之前的事件回调函数，并且根据返回值确定触发 onMouseUp/onMouseDown 事件回调函数。参数是event和treeNode(如果不在节点上，这个参数为null)；返回值为true/false
             * @cfg {Function} callback.beforeExpand=null 用用于捕获父节点展开之前的事件回调函数，并且根据返回值确定是否允许展开操作。参数是event和treeNode；返回值为true/false
             * @cfg {Function} callback.beforeCollapse=null 用于捕获父节点折叠之前的事件回调函数，并且根据返回值确定是否允许折叠操作。参数是event和treeNode；返回值为true/false
             * @cfg {Function} callback.beforeRemove=null 用于捕获节点被删除之前的事件回调函数，并且根据返回值确定是否允许删除操作。参数是event和treeNode；返回值为true/false/promise<br>
             * 当返回promise时，根据promise中的返回值决定是否继续执行删除操作。示例：
             * <pre>
             * beforeRemove: function() {
             *     return $.ajax(...).then(function() {
             *         return true; //执行删除操作，return false则不执行删除操作
             *     })
             * }
             * </pre>
             *
             * @cfg {Function} callback.onNodeCreated=null 用于捕获节点生成 DOM 后的事件回调函数。函数参数是:event、treeNode(节点数据)
             * @cfg {Function} callback.onClick=null 用于捕获节点被点击的事件回调函数，函数参数
             *      event    event对象
             *      treeNode  被点击的节点 JSON 数据对象
             *      clickFlagNumber  节点被点击后的选中操作类型，详细看下表
             *
             *      clickFlag    selectedMulti    autoCancelSelected&&event.ctrlKey / metaKey    isSelected    选中操作
             *        1            true                false                                    false    普通选中
             *        1            true                false                                    true    普通选中
             *        2            true                true                                    false    追加选中
             *        0            true                true                                    true    取消选中
             *        1            false                false                                    false    普通选中
             *        1            false                false                                    true    普通选中
             *        1            false                true                                    false    普通选中
             *        0            false                true                                    true    取消选中
             * @cfg {Function} callback.onDblClick=null 用于捕获 tree 上鼠标双击之后的事件回调函数，函数的参数是event、treeNode
             * @cfg {Function} callback.onRightClick=null 用于捕获 tree 上鼠标右键点击之后的事件回调函数，函数的参数是event、treeNode
             * @cfg {Function} callback.onMouseDown=null 用于捕获  tree上鼠标按键按下后的事件回调函数，函数的参数是event、treeNode
             * @cfg {Function} callback.onMouseUp=null 用于捕获  tree上鼠标按键松开后的事件回调函数,函数的参数是event、treeNode
             * @cfg {Function} callback.onExpand=null 用于捕获节点被展开的事件回调函数,函数的参数是event, treeNode, tmpTargetNode
             * @cfg {Function} callback.onCollapse=null 用于捕获节点被折叠的事件回调函数,函数的参数是event、treeNode
             * @cfg {Function} callback.onRemove=null 用于捕获删除节点之后的事件回调函数,函数的参数是event、treeNode
             *
             * @cfg {Function} callback.beforeCheck=null 用于捕获checkbox点击前的事件回调函数，并且根据返回值确定是否允许删除操作。函数的参数是event、treeNode
             * @cfg {Function} callback.onCheck=null 用于捕获checkbox点击之后的事件回调函数,函数的参数是event、treeNode
             *
             * @cfg {Function} callback.beforeSelect=null 利用selectNode方法选中树的节点前触发, 并且根据返回值确定是否允许选中操作, 函数的参数是event、treeNode、addFlag
             * @cfg {Function} callback.onSelect=null 利用selectNode方法选中树的节点时触发,函数的参数是event、treeNode、addFlag
             *
             * @cfg {Function} callback.beforeDrag 节点拖动前调用，并且根据返回值确定是否允许删除操作。函数参数是event, treeNode
             * @cfg {Function} callback.beforeDragOpen 节点拖动打开节点前调用，并且根据返回值确定是否允许删除操作。函数参数是event, treeNode
             * @cfg {Function} callback.beforeDrop 节点拖动放置前调用，并且根据返回值确定是否允许删除操作。函数参数是event, treeNode
             * @cfg {Function} callback.onDrag 节点拖动调用，函数参数是event, treeId, nodes
             * @cfg {Function} callback.onDragMove 节点移动调用，函数参数是event, treeId, nodes
             * @cfg {Function} callback.onDrop 节点拖动放置调用，函数参数是event, treeId, newNodes, dragTargetNode, moveType, isCopy
             * @cfg {Function} callback.beforeEditName 编辑节点名称前调用，并且根据返回值确定是否允许删除操作。函数参数是event, treeNode
             * @cfg {Function} callback.beforeRename 修改节点名称前调用，并且根据返回值确定是否允许删除操作。函数参数是event, treeNode, newName, isCancel
             * @cfg {Function} callback.onRename 修改节点名称调用，函数参数是event, treeNode, isCancel
             */
            /**
             * @cfg {Object} data 数据相关的配置
             * @cfg {Object} data.key 数据相关的键值
             * @cfg {String} [data.key.children="children"] 节点数据中保存子节点数据的属性名称。
             * @cfg {String} [data.key.name="name"]  节点数据保存节点名称的属性名称,
             * @cfg {String} [data.key.title=""]  节点数据保存节点提示信息的属性名称。[options.view.showTitle = true 时生效];如果设置为 "" ，则自动与 options.data.key.name 保持一致，避免用户反复设置
             * @cfg {String} [data.key.icon="icon"] (V2.1.0增加) 节点数据图标属性名称
             * @cfg {String} [data.key.url="url"]  节点数据保存节点链接的目标 URL 的属性名称。特殊用途：当后台数据只能生成 url 属性，又不想实现点击节点跳转的功能时，可以直接修改此属性为其他不存在的属性名称
             * @cfg {String} [data.key.iconFontEnable=false] 用于设置 iconSkin是否可以使用字体图标 默认false 兼容以前的iconSkin用法
             *
             * @cfg {String} data.key.checked="checked" 树多选时控制是否选中属性值，属性值true表示选中，false表示不选中
             *
             * @cfg {Object} data.simpleData tree使用简单数据格式时相关的设置
             * @cfg {String} [data.simpleData.enable=false] 设置加载数据、增加节点时传入的数据是否是简单格式，默认为false；如果设置为 true，请务必设置 data.simpleData 内的其他参数: idKey / pIdKey / rootPId，并且让数据满足父子关系。
             * @cfg {String} [data.simpleData.idKey=id] 节点数据中保存唯一标识的属性名称。[data.simpleData.enable = true 时生效]默认值："id"
             * @cfg {String} [data.simpleData.pIdKey=pId] 节点数据中保存其父节点唯一标识的属性名称。[data.simpleData.enable = true 时生效]默认值："pId"
             * @cfg {String} [data.simpleData.rootPId=null] 用于修正根节点父节点数据，即 pIdKey 指定的属性值。[data.simpleData.enable = true 时生效]默认值：null
             *
             * @cfg {Object} [data.keep]
             * @cfg {Boolean} [data.keep.leaf=false] 节点叶子节点属性锁，是否始终保持 isParent = false;如果设置为 true，则所有 isParent = false 的节点，都无法添加子节点。
             * @cfg {Boolean} [data.keep.parent=true] 节点父节点属性锁，是否始终保持 isParent = true;如果设置为 true，则所有 isParent = true 的节点，即使该节点的子节点被全部删除或移走，依旧保持父节点状态
             */



				/**
				 * @event onExpand
				 * @param {Event} e
				 * @param {Object} treeNode
				 * 树的节点展开时触发
				
				 */

				/**
				 * @event onCollapse
				 * @param {Event} e
				 * @param {Object} treeNode
				 * 树的节点被折叠时触发
			
				 */

				/**
				 * @event onremove
				 * @param {Event} e
				 * @param {Object} treeNode
				 * 树的节点被移除时触发
				 */

				/**
				 * @event onCheck
				 * @param {Event} e
				 * @param {Object} treeNode
				 * 树的节点被选中时触发
				 */

				/**
				 * @event onDragmove
				 * @param {Event} e
				 * @param {Object} treeNode
				 * 树的节点被拖拽移动时触发
			
				 */

				/**
				 * @event onSelect
				 * @param {Event} e
				 * @param {Object} treeNode
				 * @param {Boolean} addFlag
				 * 利用selectNode方法选中树的节点时触发
				 */